package com.qmx.launcher.activity;

import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.net.DhcpInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;

import com.koushikdutta.async.AsyncServer;
import com.koushikdutta.async.AsyncSocket;
import com.koushikdutta.async.ByteBufferList;
import com.koushikdutta.async.DataEmitter;
import com.koushikdutta.async.Util;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.ConnectCallback;
import com.koushikdutta.async.callback.DataCallback;
import com.koushikdutta.async.callback.WritableCallback;
import com.qmx.launcher.R;
import com.qmx.launcher.activity.base.BaseActivity;
import com.qmx.launcher.constant.AppConstant;
import com.qmx.launcher.service.UsbService;
import com.qmx.launcher.utils.StringUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Timer;
import java.util.TimerTask;

import es.farfuteam.vncpp.controller.CanvasActivity;
import es.farfuteam.vncpp.controller.NewConnectionActivity;

/**
 * @author ChengXiangtong
 * @create 2018/10/27
 * @Describe 无线传屏
 */
public class MiracastActivity extends BaseActivity implements ServiceConnection {

    private Switch u_disk_switch;
    private WifiManager wifi;
    private String TAG = "MiracastActivity";
    private String path = "";
    private String fileName = "";
    private String deviceName = "";
    private String productName = "";
    private String vendorId = "";
    private String productId = "";
    private String QXM_HOTS_WIFI = "QXM_HOTS_WIFI";
    private String QXM_HOTS_WIFI_PSW = "xjh201812";
    private String QXM_HOTS_CAST_PSW = "xjh2018";
    private Timer timer = new Timer();
    private String socket_target_ip = "";
    private boolean IsFirstConnect = true;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 100:
                    //                    showToast("保存成功");
                    //                    Log.i("保存成功", "保存成功=========");
                    //                    if (IsFirstConnect) {
                    //                        IsFirstConnect = false;
                    LinkMiracst();
                    //                    }
                    break;
                case 101:
                    String txt = msg.obj.toString();
                    if (!TextUtils.isEmpty(txt))
                        //                        u_disk_show.setText("读取到的数据是：" + txt);
                        break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_miracast);
        wifi = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        initViews();
        //
        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        registerReceiver(mReceiver, filter);

    }

    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        UsbService.Binder binder = (UsbService.Binder) service;
        UsbService myService = binder.getService();
        myService.setCallback(new UsbService.Callback() {
            @Override
            public void onDataChange(String mPath, String mFileName) {
                path = mPath;
                fileName = mFileName;
                Log.i("onDataChange", path + "---" + fileName);
            }
        });
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }

    @Override
    protected void onResume() {
        super.onResume();
        //开启一个服务一直运行在后台 用于接收usb的状态
        bindService(new Intent(this, UsbService.class), this, BIND_AUTO_CREATE);
        timerGetIp();

    }


    public void LinkMiracst() {
        Intent intent = new Intent(this, NewConnectionActivity.class);
        intent.putExtra("name", "QMX");
        intent.putExtra("ip", socket_target_ip);
        intent.putExtra("port", AppConstant.CAST_PORT);
        intent.putExtra("psw", QXM_HOTS_CAST_PSW);
        startActivity(intent);
        finish();
    }

    BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        public void onReceive(Context context, Intent intent) {
            UsbDevice device = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
            editor.putString(deviceName, device.getDeviceName());
            editor.putString(productName, device.getProductName());
            editor.putInt(vendorId, device.getVendorId());
            editor.putInt(productId, device.getProductId());
            editor.apply();
            Log.i("UsbDevice===", device.getDeviceName() + "  : " + device.getProductName() + " \n:" + device.getVendorId() + ":" + device.getProductId());
        }
    };

    private void initViews() {
        u_disk_switch = (Switch) findViewById(R.id.iv_switch);
        u_disk_switch.setChecked(false);
        u_disk_switch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    Log.i("onCheckedChanged", path + "---" + fileName);
                    //                    if (path.isEmpty() && fileName.isEmpty()) {
                    //                        showToast("请检查是否插入U盘");
                    //                        u_disk_switch.setChecked(false);
                    //                        return;
                    //                    }
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            createWifiHotspot();
                            showToast("投屏正在连接中...");
                            //                            getMiracastToken("192.168.43.57");
                        }
                    });
                } else {
                    //                    mHandler.post(new Runnable() {
                    //                        @Override
                    //                        public void run() {
                    //                            readFromUDisk();
                    //                            showToast("u_disk_readu_disk_readu_disk_read");
                    //                        }
                    //                    });
                }
            }
        });
    }


    private void readFromUDisk() {
        Log.i("readFromUDisk", "------------");
        readTxtFromUDisk(new File(path + "/" + fileName));

    }

    /**
     * @description 保存数据到U盘，目前是保存到根目录的
     * @author ldm
     * @time 2017/9/1 17:17
     */
    private void saveText2UDisk() {
        //项目中也把文件保存在了SD卡，其实可以直接把文本读取到U盘指定文件
        Log.i("saveText2UDisk", sharedPreferences.getString("name", "") + sharedPreferences.getString("usbPath", ""));
        String content = QXM_HOTS_WIFI + "\r\n" + QXM_HOTS_WIFI_PSW;
        File file = new File(path, fileName);
        try {
            FileWriter fw = new FileWriter(file);
            fw.write(content);
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {

        }
    }

    /**
     * 传屏socket
     *
     * @param ip
     */
    public void getMiracastToken(String ip) {
        Log.d("getMiracastToken IP", "IP:" + "---" + ip);
        AsyncServer.getDefault().connectSocket(ip, AppConstant.CAST_SOCKET_PORT, new ConnectCallback() {
            @Override
            public void onConnectCompleted(Exception ex, final AsyncSocket socket) {
                if (ex != null) {
                    //                    getMiracastToken(target_ip);
                    Log.d("getVariableToken", "连接ex出错");
                    return;
                }
                socket.setDataCallback(new DataCallback() {
                    @Override
                    public void onDataAvailable(DataEmitter emitter, ByteBufferList bb) {
                        try {
                            timer.cancel();
                            //解析socket返回的数据
                            String result = new String(bb.getAllByteArray(), "utf-8");
                            Log.i("得到数据", "socket数据：" + result);
                            String result1 = result.split(":")[0];
                            socket_target_ip = result.split(":")[1];
                            Log.d(TAG, "onDataAvailable: ");
                            if (result1.equals("cast")) {
                                IsFirstConnect = false;
                                mHandler.sendMessageDelayed(mHandler.obtainMessage(100), 5000);
                                //                                mHandler.sendEmptyMessage(100);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
                socket.setClosedCallback(new CompletedCallback() {
                    @Override
                    public void onCompleted(Exception ex) {
                        if (ex != null) {
                            if (!IsFirstConnect) {
                                IsFirstConnect = true;
                                CanvasActivity.mCanvasActivity.finish();
                            }
                            Log.d("getVariableToken", "setClosedCallback出错");
                            return;
                        }
                        Log.d("getVariableToken", "setClosedCallback");
                    }
                });
                socket.setEndCallback(new CompletedCallback() {
                    @Override
                    public void onCompleted(Exception ex) {
                        if (ex != null) {
                            Log.d("getVariableToken", "setEndCallback" + ex.getCause());
                            return;
                        }
                        Log.d("getVariableToken", "setEndCallback");
                    }
                });
                socket.setWriteableCallback(new WritableCallback() {
                    @Override
                    public void onWriteable() {
                        Log.d("getVariableToken", "WritableCallback");
                    }
                });
                //                final HashMap hashMap = new HashMap();
                //                hashMap.put("token", TokenManager.getInstance().getAuthModel().getToken());
                Util.writeAll(socket, new String("qmx2018:" + ip).getBytes(), new CompletedCallback() {
                    @Override
                    public void onCompleted(Exception ex) {
                        Log.i("writeAll", "发送数据完成:" + ip);
                        if (ex != null) {
                            Log.d("getVariableToken", "writeAll出错");
                            return;
                        }
                    }
                });
            }
        });
    }

    //
    //    private BroadcastReceiver usbReceiver = new BroadcastReceiver() {
    //
    //        @Override
    //        public void onReceive(Context arg0, Intent arg1) {
    //            List<StorageItemEntity> infos = UsbDeviceManager.getAvaliableStorage(UsbDeviceManager.listAllStorage(arg0));
    //            if (infos != null) {
    //                if (arg1.getAction().equals(Intent.ACTION_MEDIA_MOUNTED)) {
    //                    infos = UsbDeviceManager.getAvaliableStorage(UsbDeviceManager.listAllStorage(arg0));
    //                    for (StorageItemEntity sie : infos) {
    //                        Log.i("已存在的LWL", sie.toString());
    //                    }
    //
    //                } else if (arg1.getAction().equals(Intent.ACTION_MEDIA_UNMOUNTED)) {
    //                    Log.v(TAG, "ACTION_USB_DISK_UNMOUNTED::::" + arg1.getAction());
    //
    //                    List<StorageItemEntity> aliveUsb = UsbDeviceManager.getAvaliableStorage(UsbDeviceManager.listAllStorage(arg0));
    //
    //                    for (StorageItemEntity sie : aliveUsb) {
    //                        Log.i("移除的LWL", sie.toString());
    //                    }
    //
    //                }
    //            }
    //        }
    //    };

    public void readTxtFromUDisk(File file) {
        //读取文件内容
        InputStream is = null;
        try {
            is = new FileInputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //读取秘钥中的数据进行匹配
        StringBuilder sb = new StringBuilder();
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new InputStreamReader(is));
            String read;
            while ((read = bufferedReader.readLine()) != null) {
                sb.append(read);
            }
            Message msg = mHandler.obtainMessage();
            msg.what = 101;
            msg.obj = sb;
            mHandler.sendMessage(msg);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        timer.cancel();
        unbindService(this);
        unregisterReceiver(mReceiver);
    }

    public void timerGetIp() {
        WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        DhcpInfo dhcpInfo = wifiManager.getDhcpInfo();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (!printHotIp(dhcpInfo).isEmpty() || !printHotIp(dhcpInfo).equals("")) {
                    //                    getMiracastToken(printHotIp(dhcpInfo));
                    for (String ip : printHotIp(dhcpInfo)) {
                        try {
                            Thread.sleep(1000);
                            getMiracastToken(ip);
                            Log.i("getHostIP", ip);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }
                }
                //                Log.i("getHostIP", getHostIP());
                //                Log.i("timerGetIp", "timerGetIp");
            }
        }, 1000, 5000);//延时1s执行
    }

    private ArrayList<String> getConnectedHotIP() {
        ArrayList<String> connectedIP = new ArrayList<String>();
        try {
            BufferedReader br = new BufferedReader(new FileReader("/proc/net/arp"));
            String line;
            while ((line = br.readLine()) != null) {
                String[] splitted = line.split(" +");
                if (splitted != null && splitted.length >= 4) {
                    String ip = splitted[0];
                    connectedIP.add(ip);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connectedIP;
    }

    /**
     * 获取本机的ip地址
     *
     * @return
     */
    public static String getHostIP() {
        String hostIp = null;
        try {
            Enumeration nis = NetworkInterface.getNetworkInterfaces();
            InetAddress ia = null;
            while (nis.hasMoreElements()) {
                NetworkInterface ni = (NetworkInterface) nis.nextElement();
                Enumeration<InetAddress> ias = ni.getInetAddresses();
                while (ias.hasMoreElements()) {
                    ia = ias.nextElement();
                    if (ia instanceof Inet6Address) {
                        continue;// skip ipv6
                    }
                    String ip = ia.getHostAddress();
                    if (!"127.0.0.1".equals(ip)) {
                        hostIp = ia.getHostAddress();
                        break;
                    }
                }
            }
        } catch (SocketException e) {
            Log.i("yao", "SocketException");
            e.printStackTrace();
        }
        return hostIp;
    }


    //输出连接到当前设备的IP地址
    public ArrayList<String> printHotIp(DhcpInfo dhcpInfo) {
        ArrayList<String> connectedIP = getConnectedHotIP();
        //        StringBuilder resultList = new StringBuilder();

        //        System.out.print(resultList);

        if (!connectedIP.isEmpty() && connectedIP.size() != -0) {
            Log.d("---->>heww resultList=", connectedIP.get(1));
            return connectedIP;
        }
        return connectedIP;

    }

    /**
     * 创建Wifi热点
     */
    private void createWifiHotspot() {
        closeWifiHotspot();
        if (wifi.isWifiEnabled()) {
            //如果wifi处于打开状态，则关闭wifi,
            wifi.setWifiEnabled(false);
        }

        WifiConfiguration config = new WifiConfiguration();
        config.SSID = QXM_HOTS_WIFI;
        config.preSharedKey = QXM_HOTS_WIFI_PSW;
        config.hiddenSSID = true;
        config.allowedAuthAlgorithms
                .set(WifiConfiguration.AuthAlgorithm.OPEN);//开放系统认证
        config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        config.allowedKeyManagement.set(4);
        config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        config.allowedPairwiseCiphers
                .set(WifiConfiguration.PairwiseCipher.CCMP);
        config.status = WifiConfiguration.Status.ENABLED;
        //通过反射调用设置热点
        try {
            Method method = wifi.getClass().getMethod(
                    "setWifiApEnabled", WifiConfiguration.class, Boolean.TYPE);
            boolean enable = (Boolean) method.invoke(wifi, config, true);
            if (enable) {
                Log.i("热点已开启 SSID", "WIFI_HOTSPOT_SSID" + " password:123456789");
                //                textview.setText("热点已开启 SSID:" + WIFI_HOTSPOT_SSID + " password:123456789");
                saveText2UDisk();
            } else {
                //                textview.setText("创建热点失败");
                Log.i("创建热点失败", "创建热点失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.i("创建热点失败", e.getStackTrace().toString());
            //            textview.setText("创建热点失败");
        }

        Log.i("createWifiHotspot", "createWifiHotspot-==-=====");
    }

    /**
     * 关闭WiFi热点
     */
    public void closeWifiHotspot() {
        try {
            Method method = wifi.getClass().getMethod("getWifiApConfiguration");
            method.setAccessible(true);
            WifiConfiguration config = (WifiConfiguration) method.invoke(wifi);
            Method method2 = wifi.getClass().getMethod("setWifiApEnabled", WifiConfiguration.class, boolean.class);
            method2.invoke(wifi, config, false);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
